Functional Programming


모듈, 객체, 이름공간

object MyModule {
    def abs(n: Int): Int = {
        ???
    }
}
MyModule.abs(-3)

method abs 호출 시에 MyModule.abs(-3) 같은 방식으로 호출해야함. 여기서 MyModule은 abs가 속한 namespace가 됨. namespace 제공이 주된 목적인 객체를 Module이라고 부름.

용어 구분

  • procedure: side effect가 있는 함수. impure function라고 부르기도 함.
  • method: 클래스의 멤버인 함수
  • function: 일반적인 함수

고차 함수

함수를 인수로 받는 함수


In [1]:
def abs(n: Int): Int = 
    if (n < 0) -n
    else n

def formatAbs(x: Int): String = {
    val msg = " The absolute value of %d is %d."
    msg.format(x, abs(x))
}
formatAbs(-4)


Out[1]:
defined function abs
defined function formatAbs
res0_2: String = " The absolute value of -4 is 4."

In [2]:
def factorial(n: Int): Int = {
    def go(n: Int, acc: Int): Int =
        if (n <= 0) acc
        else go(n-1, acc*n)
    go(n, 1)
}

def formatFactorial(x: Int): String = {
    val msg = " The factorial of %d is %d."
    msg.format(x, factorial(x))
}
formatFactorial(5)


Out[2]:
defined function factorial
defined function formatFactorial
res1_2: String = " The factorial of 5 is 120."

DRY(Don't Repeat Yourself)


In [3]:
// 파라미터 f는 Int를 인수로 받아서 Int를 리턴하는 함수
def formatResult(name: String, n: Int, f: Int => Int): String = {
    val msg= "The %s of %d is %d."
    msg.format(name, n, f(n))
}
formatResult("absolute", -4, abs)
formatResult("factorial", 5, factorial)


Out[3]:
defined function formatResult
res2_1: String = "The absolute of -4 is 4."
res2_2: String = "The factorial of 5 is 120."

다형적 함수: 형식에 대한 추상

  • 단형적 함수(monomorphic function): 특정 형식(type)에만 작용하는 함수
  • 다형적 함수(polymorphic function): 임의의 형식(type)에 작용하는 함수

monomorphic function의 예

String 배열에서 String을 찾는 함수

def findFirst(ss: Array[String], key: String): Int = {
    @annotation.tailrec
    def loop(n: Int): Int = 
        if(n >= ss.length) -1
        else if(ss(n) == key) n
        else loop(n+1)
    loop(0)
}

polymorphic function의 예

임의의 형식 A의 배열에서 특정 A를 찾는 함수

def findFirst[A](ss: Array[A], p: A => Boolean): Int = { 
    @annotation.tailrec
    def loop(n: Int): Int = 
        if(n >= ss.length) -1
        else if(p(as(n))) n // 상등판정을 하드코딩하는 대신 배열의 각 요소를 검사하는 함수를 사용
        else loop(n+1)
    loop(0)
}

연습문제 2.2

Array[A]가 주어진 비교 함수에 의거해서 정렬되어 있는지 점검하는 isSorted함수를 구현하라. 서명은 다음과 같다.

def isSorted[A](as: Array[A], ordered: (A,A) => Boolean): Boolean

In [1]:
def isSorted[A](as: Array[A], ordered: (A, A) => Boolean): Boolean = {
    def loop(n: Int): Boolean =
        if (n == as.length -1) true
        else if (ordered(as(n), as(n+1))) loop(n+1)
        else false
    loop(0)
}


Out[1]:
defined function isSorted

In [2]:
def bigger(a: Int, b: Int): Boolean = 
    a < b


Out[2]:
defined function bigger

In [3]:
isSorted(Array(1, 3, 2), bigger)


Out[3]:
res2: Boolean = false